package com.learning.demos;

import org.springframework.security.access.method.P;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 *  可重入锁（又名递归锁）：同一线程外层函数获取锁之后，内层递归函数仍能获取该锁，即线程可以进入任何一个它已经拥有的锁所同步着的代码块；
 *  ReentrantLock  synchronized  防止死锁
 *
 * @author adolphw
 */
public class ReenterLockDemo {

    public static void main(String[] args) {
        Phone phone = new Phone();

        new Thread(() -> {
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t1").start();

        new Thread(() -> {
            try {
                phone.sendSMS();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, "t2").start();


        TelPhone telPhone = new TelPhone();
        Thread t3 = new Thread(telPhone);
        Thread t4 = new Thread((telPhone));

        t3.start();
        t4.start();
    }



}

class Phone{
    public synchronized void sendSMS() throws Exception {
        System.out.println(Thread.currentThread().getId()+"\t sendSMS" );

        sendEmail();
    }

    public synchronized void sendEmail() throws Exception {
        System.out.println(Thread.currentThread().getId()+"\t sendEmail" );
    }
}


class TelPhone implements  Runnable{
    Lock lock = new ReentrantLock();


    @Override
    public void run() {
        get();
    }

    public void get() {
        // 锁上几把 就要开几把锁，否则线程卡死
        lock.lock();
        lock.lock();

        try {
            System.out.println(Thread.currentThread().getId()+"\t get");
            set();

        }finally {
            lock.unlock();
            lock.unlock();
        }
    }

    public void set() {
        lock.lock();

        try {
            System.out.println(Thread.currentThread().getId()+"\t set");

        }finally {
            lock.unlock();
        }
    }
}